home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_CtlPoints / ControlView.m < prev    next >
Text File  |  1992-12-19  |  14KB  |  584 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    ControlView.m
  35.  *
  36.  *    Version:    2.0
  37.  *    Author:    Ken Fromm
  38.  *    History:
  39.  *            03-07-91        Added this comment.
  40.  */
  41.  
  42. #import "ControlPoint.h"
  43. #import "ControlView.h"
  44. #import "ControlViewWraps.h"
  45.  
  46. #import <appkit/Button.h>
  47. #import <appkit/Control.h>
  48. #import <appkit/Matrix.h>
  49. #import <appkit/NXImage.h>
  50. #import <appkit/TextField.h>
  51. #import <dpsclient/wraps.h>
  52.  
  53. @implementation ControlView
  54.  
  55. - initFrame:(const NXRect *) frameRect
  56. {
  57.     float        ViewRect[4];
  58.  
  59.     NXSize    size;
  60.  
  61.     [super initFrame:frameRect]; 
  62.     [self allocateGState]; 
  63.  
  64.     NX_MALLOC(XYPoints, float, MAX_ARRAY);
  65.     NX_MALLOC(OpsBuffer, char, MAX_UPATHOPS); 
  66.     NX_MALLOC(XYBuffer, float, (MAX_UPATHPTS));
  67.  
  68.     ViewRect[0] = ViewRect[1] = 0.0;
  69.     ViewRect[2] = bounds.size.width;
  70.     ViewRect[3] = bounds.size.height;
  71.     PSWDefsView (BGCOLOR, BGCOLORSTR, BGWIDTHSTR, ViewRect);
  72.     
  73.     srand(1);
  74.     indexOfPoints = 0;
  75.  
  76.     size.width = size.height = FIGURESIZE;
  77.     imageId = [[[NXImage alloc]  initSize:&size]  setFlipped:NO];
  78.  
  79.     [self    makePoints:self];
  80.     
  81.     return self;
  82. }
  83.  
  84. /*
  85. * Free the buffers
  86. */ 
  87. - free
  88. {
  89.     if (OpsBuffer)
  90.         NX_FREE(OpsBuffer);
  91.     if (XYPoints)
  92.         NX_FREE(XYPoints);
  93.     if (XYBuffer)
  94.         NX_FREE(XYBuffer);
  95.     
  96.     return [super free];
  97. }
  98.  
  99. /* The following methods are used to obtain the ids of the appropriate text fields.  They
  100. * were created by interface builder.
  101. */
  102. -setDrawMethodsMatrix:anObject
  103. {
  104.     drawMethodsMatrix = anObject;
  105.     return self;
  106. }
  107.  
  108. -setDisplayTimesMatrix:anObject
  109. {
  110.     displayTimesMatrix = anObject;
  111.     return self;
  112. }
  113.  
  114. -setNumberPointsMatrix:anObject
  115. {
  116.     numberPointsMatrix = anObject;
  117.     numberOfPoints = [numberPointsMatrix selectedTag];
  118.     return self;
  119. }
  120.  
  121. -setControlPoint:anObject
  122. {
  123.     controlPoint = anObject;
  124.     return self;
  125. }
  126.  
  127. -setButtonTitle:(OP) title
  128. {
  129.     if (title == FILL)
  130.     {
  131.         [[drawMethodsMatrix cellAt:2 :0] setTitle:"ufill"];
  132.         [[drawMethodsMatrix cellAt:3 :0]setTitle:"rectfill"];
  133.     }
  134.     else
  135.     {
  136.         [[drawMethodsMatrix cellAt:2 :0] setTitle:"ustroke"];
  137.         [[drawMethodsMatrix cellAt:3 :0]setTitle:"rectstroke"];
  138.     }
  139.  
  140.     return self;
  141. }
  142.  
  143. -setButtonEnable:(BOOL) enable
  144. {
  145.     [[drawMethodsMatrix cellAt:3 :0] setEnabled:enable];
  146.  
  147.     return self;
  148. }
  149.  
  150. -psTrace:sender
  151. {
  152.     if (PSTrace == NO)
  153.         [[sender selectedCell] setTitle:"Trace On"];
  154.     else
  155.         [[sender selectedCell] setTitle:"Trace Off"];
  156.  
  157.     PSTrace = !PSTrace;
  158.     
  159.     return self;
  160. }
  161.  
  162. -configureDependence:sender
  163. {
  164.     [controlPoint  deviceDependence:[sender state]];
  165.     [self  eraseTimes:self];
  166.  
  167.     return self;
  168. }
  169.  
  170. -configurePoints:sender
  171. {
  172.     
  173.     numberOfPoints = [numberPointsMatrix selectedTag];
  174.     
  175.     /* Choose a new starting index to instill a little change in the display. */
  176.     indexOfPoints = (rand () % (MAX_POINTS - numberOfPoints + 1)) * 2;
  177.  
  178.     [self eraseTimes:self];
  179.     return self;
  180. }
  181.  
  182. /*
  183. *   This method fills up the array of points randomly. If the number of points to draw
  184. *   is different from the previous time, then a new place in the array will be selected for the
  185. *   points (except for the case of the largest number of points, in this instance the 0 index will
  186. *   be used). This random selection of indices introduces a little bit of change in the display.
  187. */
  188. -makePoints:sender
  189. {
  190.     int          i;
  191.     
  192.     for (i = 0; i < MAX_ARRAY; i = i +2)
  193.     {
  194.         XYPoints[i] = (rand () % (long)((bounds.size.width -8) * 100) + 400) * 0.01;
  195.         XYPoints[i+1] = (rand () % (long)((bounds.size.height -8) * 100) + 400) * 0.01;
  196.     }
  197.  
  198.     return self;
  199. }
  200.  
  201. -eraseTimes:sender
  202. {
  203.     int        i;
  204.     
  205.     for (i = 0; i < [displayTimesMatrix cellCount]; i++)
  206.         [[displayTimesMatrix cellAt:i :0] setStringValue:""];
  207.  
  208.     return self;
  209. }
  210.  
  211. /* Draw using the method selected. */
  212. -drawViewOne:sender
  213. {
  214.     int    i, row;
  215.     
  216.     row = [sender selectedRow];
  217.         drawFlags.field = 0x80 >> row;
  218.     
  219.     [self display];
  220.  
  221.     return self;
  222. }
  223.  
  224. /* Draw using all the methods. */
  225. -drawViewAll:sender
  226. {
  227.     drawFlags.field = DRAWALL;
  228.  
  229.     [self display];
  230.  
  231.     return self;
  232. }
  233.  
  234.  
  235. /*
  236.  *  Below are six methods that use different approaches to drawing control points.
  237.  */
  238.  
  239. /* The drawing will center around the point passed in.*/
  240. -drawBasic:(int) cell
  241. {
  242.     int        ElapsedTime, i;
  243.     
  244.     char        *basicProc, *basicOp;
  245.     
  246.     basicProc = [controlPoint  getBasicProc];
  247.     basicOp = [controlPoint  getBasicOp];
  248.  
  249.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  250.         PSWEraseView();
  251.         PSsetlinewidth(0.15);
  252.         PSWMarkTime(); NXPing();    
  253.             if (PSTrace)
  254.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  255.  
  256.             for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
  257.                 PSWBasic(XYPoints[i], XYPoints[i+1], basicProc, basicOp);
  258.  
  259.             if (PSTrace)
  260.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  261.         PSWReturnTime (&ElapsedTime);
  262.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  263.  
  264.     return self;
  265. }
  266.  
  267. /*
  268.  * Cache a single user path. Translate to each location and then
  269.  * image the user path.
  270.  */
  271. -drawUserCache:(int) cell
  272. {
  273.     int         ElapsedTime, i, i_pt, i_op, j;
  274.     
  275.     char        *userOp, *userOpsArray;
  276.     
  277.     float        *userPtsArray; 
  278.  
  279.     userPtsArray = [controlPoint  getUserPtsArray];
  280.     userOpsArray = [controlPoint  getUserOpsArray];
  281.     userOp = [controlPoint  getUserOp];
  282.     
  283.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  284.         PSWEraseView();
  285.         PSsetlinewidth(0.15);
  286.         PSWMarkTime ();  NXPing();
  287.         
  288.             /*
  289.             *  Places a user path description for a generic control
  290.             *  point into the OpsBuffer and XYBuffer.
  291.             */
  292.             i_op = i_pt = 0;
  293.             OpsBuffer[i_op++] = dps_ucache;
  294.             
  295.             /* The bounding box is the size of the control point. */
  296.             XYBuffer[i_pt++] = -FIGURESIZE/2;
  297.             XYBuffer[i_pt++] = -FIGURESIZE/2;
  298.             XYBuffer[i_pt++] = FIGURESIZE/2;
  299.             XYBuffer[i_pt++] = FIGURESIZE/2;
  300.             OpsBuffer[i_op++] = dps_setbbox;
  301.         
  302.             XYBuffer[i_pt++] = 0;
  303.             XYBuffer[i_pt++] = 0;
  304.             OpsBuffer[i_op++] = dps_moveto;
  305.  
  306.             for (j = 1; j <= userPtsArray[0]; j++)
  307.                 XYBuffer[i_pt++] = userPtsArray[j];
  308.  
  309.             for (j = 1; j <= (int) userOpsArray[0]; j++)
  310.                 OpsBuffer[i_op++] = userOpsArray[j];
  311.  
  312.             /*
  313.             * Performs an initial translate to the first location
  314.             * and then performs a relative translation thereafter.
  315.             */
  316.             PSgsave();
  317.             if (PSTrace)
  318.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  319.  
  320.             PStranslate(XYPoints[indexOfPoints], XYPoints[indexOfPoints+1]);
  321.             for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
  322.             {
  323.                 PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
  324.                 PStranslate(XYPoints[i+2] - XYPoints[i], XYPoints[i+3] - XYPoints[i+1]);
  325.             }
  326.  
  327.             if (PSTrace)
  328.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  329.             PSgrestore();
  330.         PSWReturnTime (&ElapsedTime);
  331.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  332.  
  333.     return self;
  334. }
  335.  
  336. /* Represents the control points as a large user path comprised of a set of sub user paths. */
  337. -drawUserPath:(int) cell
  338. {
  339.     int         ElapsedTime, i,  i_pt, i_op, j;
  340.     
  341.     char        *userOp, *userOpsArray;
  342.     
  343.     float        *userPtsArray; 
  344.  
  345.     userPtsArray = [controlPoint  getUserPtsArray];
  346.     userOpsArray = [controlPoint  getUserOpsArray];
  347.     userOp = [controlPoint  getUserOp];
  348.     
  349.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  350.         PSWEraseView();
  351.         PSsetlinewidth(0);
  352.         PSWMarkTime ();  NXPing();
  353.             /* Place the bounding box in the user path description. */
  354.             XYBuffer[0] = bounds.origin.x;
  355.             XYBuffer[1] = bounds.origin.y;
  356.             XYBuffer[2] = bounds.origin.x + bounds.size.width;
  357.             XYBuffer[3] = bounds.origin.y + bounds.size.height;
  358.             OpsBuffer[0] = dps_setbbox;
  359.         
  360.             if (PSTrace)
  361.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  362.  
  363.             i = 0; i_pt = 4; i_op = 1;
  364.             while (i < numberOfPoints * 2)
  365.             {
  366.                 /* 
  367.                 * This check sends the array to the server if the array
  368.                 * limit has been reached.
  369.                 */
  370.                 if ((i_pt + userPtsArray[0] > MAX_UPATHPTS) ||
  371.                     (i_op + (int) userOpsArray[0] > MAX_UPATHOPS))
  372.                 {
  373.                     PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
  374.                     i_pt = 4; i_op = 1;
  375.                 }
  376.             
  377.                 XYBuffer[i_pt++] = XYPoints[indexOfPoints + i++];
  378.                 XYBuffer[i_pt++] = XYPoints[indexOfPoints + i++];
  379.                 OpsBuffer[i_op++] = dps_moveto;
  380.  
  381.                 for (j = 1; j <= userPtsArray[0]; j++, i_pt++)
  382.                     XYBuffer[i_pt] = userPtsArray[j];
  383.                 
  384.                 for (j = 1; j <= (int) userOpsArray[0]; j++, i_op++)
  385.                     OpsBuffer[i_op] = userOpsArray[j];
  386.             }
  387.             PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
  388.  
  389.             if (PSTrace)
  390.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  391.         PSWReturnTime (&ElapsedTime);
  392.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  393.  
  394.     return self;
  395. }
  396.  
  397. /*
  398.  *  Here we have to calculate the offset from the center because
  399.  *  rectfill starts drawing at the location passed in.
  400.  */
  401. -drawRectOp:(int) cell
  402. {
  403.     int        ElapsedTime, i, j;
  404.     
  405.     char        *rectOp;
  406.     
  407.     rectOp = [controlPoint  getRectOp];
  408.     
  409.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  410.         PSWEraseView();
  411.         PSsetlinewidth(0);
  412.         PSWMarkTime (); NXPing();        
  413.             if (PSTrace)
  414.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  415.  
  416.             /* Draw the rectangles if the array limit has been reached. */
  417.             for (i = indexOfPoints, j = 0; i < indexOfPoints + (numberOfPoints*2); i = i+2, j = j+4)
  418.             {
  419.                 /* Flush the buffer if full. */
  420.                 if (j+3 >  MAX_RECTPTS)
  421.                 {
  422.                     PSWRectDraw (XYBuffer, j, rectOp);
  423.                     j = 0;
  424.                 }
  425.                 XYBuffer[j] = XYPoints[i] - RECTOFFSET;
  426.                 XYBuffer[j+1] = XYPoints[i+1] - RECTOFFSET;
  427.                 XYBuffer[j+2] = RECTSIZE;
  428.                 XYBuffer[j+3] = RECTSIZE;
  429.             }
  430.             PSWRectDraw (XYBuffer, j, rectOp);
  431.  
  432.             if (PSTrace)
  433.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  434.         PSWReturnTime (&ElapsedTime);
  435.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  436.  
  437.     return self;
  438. }    
  439.  
  440. /*
  441. * Draws the control point into the NXImage and then composites it at each
  442. * control point location.
  443. */
  444. -drawComposite:(int) cell
  445. {
  446.     int            ElapsedTime, i;
  447.  
  448.     NXPoint        point;
  449.  
  450.     [controlPoint drawImage:imageId];
  451.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  452.         PSWEraseView();
  453.         PSWMarkTime (); NXPing();
  454.             if (PSTrace)
  455.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  456.  
  457.             /* The adjustment centers the rectangle on the point location. */
  458.             for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
  459.             {
  460.                 point.x = XYPoints[i] - FIGUREHALFSIZE;
  461.                 point.y = XYPoints[i+1] - FIGUREHALFSIZE;
  462.                 [imageId composite:NX_SOVER  toPoint:&point];
  463.             }
  464.  
  465.             if (PSTrace)
  466.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  467.         PSWReturnTime (&ElapsedTime);
  468.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  469.  
  470.     return self;
  471. }
  472.  
  473. /*
  474. * Performs a moveto show for each control point.
  475. */
  476. -drawShow:(int) cell
  477. {
  478.     int        ElapsedTime, i;
  479.  
  480.     char        fontchar[2];
  481.  
  482.     fontchar[0] = [controlPoint getChar];
  483.     fontchar[1] = 0;
  484.     [controlPoint selectFont:FONTSIZE];
  485.  
  486.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  487.         PSgsave();
  488.         PSWEraseView();
  489.         PSWMarkTime (); NXPing();
  490.             if (PSTrace)
  491.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  492.  
  493.             for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
  494.                 PSWShow(XYPoints[i], XYPoints[i+1], fontchar);
  495.  
  496.             if (PSTrace)
  497.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  498.         PSWReturnTime (&ElapsedTime);
  499.         PSgrestore();
  500.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  501.  
  502.     return self;
  503. }
  504.  
  505. /*
  506. * Places the characters and relative offsets into arrays and executes
  507. * a single xyshow.
  508. */
  509. -drawXYShow:(int) cell
  510. {
  511.     int        ElapsedTime, i, j;
  512.  
  513.     char        fontchar;
  514.  
  515.     fontchar = [controlPoint getChar];
  516.     /*
  517.     * Place the characters into the character string for xyshow.
  518.     * Terminate the string with a NULL character.
  519.     */
  520.     for (i = 0; i < numberOfPoints; i++)
  521.         OpsBuffer[i] = fontchar;
  522.     OpsBuffer[i] = 0;
  523.  
  524.     [controlPoint selectFont:FONTSIZE];
  525.     
  526.     [[displayTimesMatrix cellAt:cell :0] setStringValue:""];
  527.         PSgsave();
  528.         PSWEraseView();
  529.         PSWMarkTime (); NXPing();
  530.             /* Calculate the displacement from the previous character. */
  531.             for (i = indexOfPoints+2, j = 0; i < indexOfPoints + (numberOfPoints*2); i++, j++)
  532.                 XYBuffer[j] = XYPoints[i] - XYPoints[i-2];
  533.             
  534.             /*
  535.             *  Provide a dummy set of displacements for the move after
  536.             *  the last character has been shown.
  537.             */
  538.             XYBuffer[j++] = 0;
  539.             XYBuffer[j++] = 0;
  540.  
  541.             if (PSTrace)
  542.                 DPSTraceContext(DPSGetCurrentContext(), YES);
  543.  
  544.             /* Establish a current point and then execute the xyshow. */
  545.             PSWXYShow(XYPoints[indexOfPoints], XYPoints[indexOfPoints+1],
  546.                 OpsBuffer, XYBuffer, j);        
  547.  
  548.             if (PSTrace)
  549.                 DPSTraceContext(DPSGetCurrentContext(), NO);
  550.         
  551.         PSWReturnTime (&ElapsedTime);
  552.         PSgrestore();
  553.     [[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
  554.  
  555.     return self;
  556. }
  557.  
  558. /* Messaged by the "display" method.  This method should not be called directly. */
  559. -drawSelf:(NXRect *)r :(int) count
  560. {
  561.         
  562.     PSWEraseView();
  563.  
  564.     PSsetgray(NX_BLACK);
  565.     if (drawFlags.flags.basic)
  566.         [self drawBasic:0];
  567.     if (drawFlags.flags.usercache)
  568.         [self drawUserCache:1];
  569.     if (drawFlags.flags.userpath)
  570.         [self drawUserPath:2];
  571.     if (drawFlags.flags.rectop  && [[drawMethodsMatrix cellAt:3 :0] isEnabled])
  572.         [self drawRectOp:3];
  573.     if (drawFlags.flags.composite)
  574.         [self drawComposite:4];
  575.     if (drawFlags.flags.show)
  576.         [self drawShow:5];
  577.     if (drawFlags.flags.xyshow)
  578.         [self drawXYShow:6];
  579.  
  580.     return self;
  581. }
  582.  
  583. @end
  584.